#!/usr/sbin/rsct/perl5/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 1999,2002 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
#"@(#)50   1.31.1.3   src/rsct/rmc/cli/bin/lsrsrcdef.perl, rmccli, rsct_rpyxh, rpyxht1f3 8/1/02 15:26:48"
######################################################################
#                                                                    #
# Module: lsrsrcdef                                                  #
#                                                                    #
# Purpose:                                                           #
#   lsrsrcdef - Lists a resource or resource class definition.       #
#                                                                    #
# Syntax:                                                            #
#   lsrsrcdef [-h] [-c] [-A p|d] [-p Property] [-s] [-e] [-v]        #
#             [-l|-i|-t|-d|-D Delimiter] [-x] [-T] [-V]              #
#             [Resource_class [Attr...]                              #
#                                                                    #
# Flags:                                                             #
#   -h      Help. Writes this command's usage statement to stdout.   #
#   -c      Class. Displays the resource class definition. By        #
#           default, the resource definition is displayed. Combine   #
#           with the -A p|d flag to display the resource class       #
#           definition for persistent or dynamic attributes.         #
#           Use the -c flag alone, without the -A p|d flag, to see   #
#           the resource class definition.                           #
#   -A      Attribute type. Specifies the attribute type. Either     #
#           persistent or dynamic attribute definitions may be       #
#           displayed. Use this flag with the -c flag for the        #
#           persistent or dynamic attribute definitions of the       #
#           resource class.                                          #
#           p - Displays only persistent attributes                  #
#           d - Displays only dynamic attributes                     #
#   -p Property Displays attributes with the specified Property. By  #
#           default, only public attributes are displayed. To        #
#           display all attribute definitions regardless of the      #
#           property, use the -p 0 flag. Refer to ct_mc.h for        #
#           persistent and dynamic property values. An or-ing of the #
#           properties will be accepted to display only attributes   #
#           that have any of the specified properties.               #
#   -s      Structured Data. Displays the structured data definition.#
#           Specify this flag for the structured data definition to  #
#           be expanded so that each element definition of the       #
#           structured data attributes is displayed.                 #
#   -e      Expands the descriptions. By default the definitions are #
#           displayed, but the textual descriptions are not          #
#           displayed because they may be lengthy. Specify this flag #
#           to see both the definitions and descriptions.            #
#   -v      Display attribute valid values. The -s flag must be      #
#           given in conjunction with the -v flag in order to view   #
#           valid values of structured data elements (if present).   #
#   -l      Specifies long formatted output, one entry per line.     #
#           This is the default display format. If the lsrsrcdef     #
#           command is issued with the -l flag, but without a        #
#           resource class name, the -l flag is ignored when the     #
#           command returns the list of defined resource class names.#
#   -i      Input format. Generates a template of the Resource Data  #
#           Input File which can then, after appropriate editing, be #
#           used as input to the mkrsrc command. The output is       #
#           displayed in long (stanza) format. All required and      #
#           optional attributes that can be used to define a         #
#           resource are displayed. The attribute data type is       #
#           displayed as the value in the Attr=value pairs. It is    #
#           suggested that when you use this flag, the output of the #
#           lsrsrcdef command be directed to a file.                 #
#           The -i flag overrides the -Ad, -s, and -v flags.         #
#   -t      Specifies tabular formatted output. Each attribute is    #
#           displayed in a separate column, one resource per line.   #
#   -d      Specifies delimiter-formatted output. The default        #
#           delimiter is a colon (:). Use the -D flag to change the  #
#           default delimiter.                                       #
#   -D Delimiter    Specifies delimiter-formatted output that uses   #
#           the specified delimiter. Use this flag to specify        #
#           something other than the default colon (:). An example   #
#           is when the data to be displayed contains colons. Use    #
#           this flag to specify a delimiter of one or more          #
#           characters.                                              #
#   -x      Exclude header. Suppress header printing.                #
#   -T      Trace. Writes the command's trace messages to standard   #
#           error. For your software-service organization's use only.#
#   -V      Verbose. Writes this command's verbose messages to       #
#           standard out.                                            #
#                                                                    # 
# Operands:                                                          #
#   Resource_class  Resource class name. The name of the resource    #
#                   class whose attribute definitions are to be      #
#                   displayed. If no Resource_class operand is       #
#                   specified, a list of all of the resource class   #
#                   names is displayed.                              #
#                                                                    #
#   Attr            If a Resource_class operand is specified, zero   #
#                   or more attribute names can be specified. If no  #
#                   Attr operand is specified, the definition for    #
#                   all the attributes for the Resource_class are    #
#                   listed. Specific attribute names may be          #
#                   specified to control which attributes are        #
#                   displayed and their order. Specify only          #
#                   persistent attribute names when the -A p flag is #
#                   used. Specify only dynamic attribute names when  #
#                   the -A d flag is used. Attributes must be        #
#                   separated by spaces.                             #
#                                                                    #
# Description:                                                       #
#   The lsrsrcdef command lists the definition of a resource class,  #
#   or the persistent or dynamic attributes of a resource instance   #
#   or a resource class.                                             #
#                                                                    #
#   Use lsrsrcdef with no operands specified to get a list of all    #
#   resource class names.                                            #
#                                                                    #
#   To see just the resource class definition, specify the -c flag   #
#   and a Resource_class operand without specifying the -A flag.     #
#                                                                    #
#   To see the persistent or dynamic attribute definitions of the    #
#   resource class, specify a Resource_class operand and the -c flag #
#   with the appropriate -A flag (-A d for dynamic attribute or -A p #
#   for persistent attribute definitions). To see the persistent or  #
#   dynamic attribute definitions for a resource, specify the        #
#   appropriate -A p|d flag without the -c flag.                     #
#                                                                    #
#   By default, when no Attr operands are specified on the command   #
#   line, only the definitions for public attributes are displayed.  #
#   To override this default, use the -p flag or specify the name of #
#   the attribute you wish to display.                               #
#                                                                    #
#   By default, for the attributes that contain descriptions, the    #
#   descriptions are not displayed. Specify the -e flag to display   #
#   the descriptions. Because some of the descriptions are very      #
#   long, the default is not to display them. If descriptions for    #
#   members of the valid_vals list are available, they are displayed #
#   with the -e flag as well.                                        #
#                                                                    #
#   By default, for attributes that have defined valid values, the   #
#   valid values are not displayed.  Specify the -v flag to display  # 
#   the valid values. Specify the -s flag with the -v flag to view   #
#   the structured data elements' valid values. Valid_vals and       #
#   valid_vals_label fields are blank for pointer data types. Fields #
#   are also blank if the attribute is an SD or SD array and the -s  #
#   flag was not given. Because valid values are not returned as     #
#   part of the base definition of the resource or resource class,   #
#   and extra calls to RMC must be made to retrieve the valid values,#
#   the default is not to display them.                              #
#                                                                    #
# Exit Values:                                                       #
#   0  MC_CLI_SUCCESS        Command completed successfully.         #
#   1  MC_CLI_RMC_ERROR      Command terminated due to an underlying #
#                            RMC error.                              #
#   2  MC_CLI_ERROR          Command terminated due to an underlying #
#                            error in the command script.            #
#   3  MC_CLI_BAD_FLAG       Command terminated due to user          #
#                            specifying an invalid flag.             #
#   4  MC_CLI_BAD_OPERAND    Command terminated due to user          #
#                            specifying a bad operand.               #
#   5  MC_CLI_USER_ERROR     Command terminated due to a user error. #
#                            For example specifying an undefined     #
#                            Resource name as the Resource operand.  #
#                                                                    #
# Examples:                                                          #
#   lsrsrcdef                    (lists all resource class names     #
#   lsrsrcdef -c IBM.Processor   (lists resource class definition)   #
#   lsrsrcdef -c -Ap IBM.Condition (lists resouce class pers at defs)#
#   lsrsrcdef IBM.Host           (lists resource persistent attr def)#
#   lsrsrcdef -Ad IBM.Host       (lists resouce dynamic attr defs)   #
#   lsrsrcdef -c -e IBM.Hostt    (lists resource class def with desc)#
#   lsrsrcdef -Ap IBM.FileSystem Name Vfs                            #
#   lsrsrcdef -s -Ap IBM.EventResponse Actions (list the expanded    #
#                                 SD def for SD attr Actions.)       #
#   lsrsrcdef -v -Ap IBM.FileSystem (list resource persistent attr   #
#                                    defs with attr valid values)    #
#                                                                    #
# Man Page:                                                          #
#   For the most current detailed description of this command see    #
#   the lsrsrcdef man page in /usr/sbin/rsct/man.                    #
#                                                                    #
#--------------------------------------------------------------------#
# Inputs:                                                            #
#   /usr/sbin/rsct/msgmaps/mccli.lsrsrcdef.map - message mapping     #
#   /usr/sbin/rsct/msgmaps/mccli.mccli.map - message mapping         #
#                                                                    #
# Outputs:                                                           #
#   stdout - display of the resource class definitions.              #
#   stderr - any error message.                                      #
#                                                                    #
# External Ref:                                                      #
#   Commands: ctdspmsg                                               #
#   Modules:  MC_cli_utils.pm, MC_cli_display_utils.pm, MC_cli_rc.pm #
#             CT_cli_utils.pm, CT_cli_data_type_utils                #
#   Extensions:  CT::MC, CT::MCerr, CT::CT                           #
#   Perl library routines: Getopt::Std                               #
#                                                                    #
# Tab Settings:                                                      #
#   4 and tabs should be expanded to spaces before saving this file. #
#   in vi:  (:set ts=4  and   :%!expand -4)                          #
#                                                                    #
# Change Activity:                                                   #
#   990528 SAB 48419: Initial design & write.                        #
#   010311 SAB 63852: Prepared for GA.                               #
#   010806 YSK 75111: Added -v, valid values support.                #
#   020307 JAC 80687: Remove -v and go back to old usage.            #
#   020726 JAC 84819: Change -a to -A for cmd consistency.           #
#   020801 JAC 85417: Update usage message.                          #
######################################################################

#--------------------------------------------------------------------#
# General Program Flow/Logic:                                        #
#                                                                    #
# A. Parse command line flags and operands, determine which flavor   #
#    of this command we are actually invoking.                       #
#    This command allows a user to see the Resource Definitions.     #
#    They can select to see one of:                                  #
#       * The Resource Class Definition                              #
#       * The Resource Class Persistent Attributes Definitions       #
#       * The Resource Class Dynamic Attributes Definitions          #
#       * The Resource Persistent Attributes Definitions             #
#       * The Resource Dynamic Attributes Definitions                #
#       * Structured Data Definitions for Resource Class P & D Attr  #
#       * Structured Data Definitions for Resource P & D Attr Defs.  #
#       * Resource Data Input File format for mkrsrc or chrsrc.      #
# B. Initialize a session with RMC.                                  #
# C. Query the definition of the specified resource class using RMC. #
# D. Display the results.                                            #
# E. Cleanup.                                                        #
#--------------------------------------------------------------------#

#--------------------------------------------------------------------#
# Included Libraries and Extensions                                  #
#--------------------------------------------------------------------#
use lib "/usr/sbin/rsct/pm";
use locale;
use Getopt::Std; 

use CT::CT qw(:ct_data_type_t);

use autouse CT_cli_utils => qw(
    printIMsg
    printEMsg
);
use autouse CT_cli_data_type_utils => qw(
    data_type_to_string
);

use CT::MC qw(
    :mc_pattr_props_t
    :mc_qdef_opts_t
    :mc_sd_usage_t
    :mc_vv_usage_t
    :mc_action_type_t

    qdef_resource_class_bp
    qdef_p_attribute_bp
    qdef_d_attribute_bp
    qdef_sd_bp    
    qdef_valid_values_bp
    free_response
);

use CT::MCerr;

use MC_cli_rc qw(:return_codes);
use autouse MC_cli_utils => qw(
    init_session 
    term_session
    get_p_attr_defs
    get_d_attr_defs
    translate_lsAOpt
    qdef_resource_class 
    required_attr
    build_HoAttr
    error_exit
    printCEMsg
);
use autouse MC_cli_display_utils => qw(
    display_resource_class_names
    display_resource_data
    convert_properties
    convert_variable_type
    convert_variety_list
    convert_valid_values
    convert_sd_valid_values
    convert_valid_values_label
    convert_sd_valid_values_label                           
);


#--------------------------------------------------------------------#
# Global Variables                                                   #
#--------------------------------------------------------------------#
$TRUE = 1;
$FALSE = 0;

$Verbose = $FALSE;                      # default - verbose turned off

# By default output is written in long format 
$Opt_Long_Format = $TRUE;               # default - see -l (long form)
$Opt_Table_Format = $FALSE;             # default - see -t (table)
$Opt_Delm_Format = $FALSE;              # default - see -d (delimiter)
$Opt_Delm_Str = ":";                    # default - see -D (colon :) 
$Opt_No_HDR = $FALSE;                   # default - see -x
$Opt_Exp_Desc = $FALSE;                 # default - see -e
$Opt_LS_Class_Def = $FALSE;             # default - see -c
$Opt_SD_Def = $FALSE;                   # default - see -s 
$Opt_LS_Input_File = $FALSE;            # default - see -i
$Opt_LS_Class = $FALSE;                 # default (no -A flag) 
$Opt_LS_DAttr = $FALSE;                 # default - see -A 
$Opt_LS_PAttr = $TRUE;                  # default - see -A 
$Opt_Valid_Vals = $FALSE;               # default - see -v 

$PROGNAME = "lsrsrcdef";                # Program Name for messages
$MSGCAT = "mccli.cat";                  # msg catalogue for this cmd

$CTDIR = "/usr/sbin/rsct";              # RSCT root directory
$CTBINDIR = "$CTDIR/bin";               # Cluster Bin directory path
$LSMSG = "$CTBINDIR/ctdspmsg";          # display message rtn.
$ENV{'MSGMAPPATH'} = "$CTDIR/msgmaps";  # msg maps used by $LSMSG
%Cleanup = ();                          # Hash of items to cleanup
                                        # {Session} $session to term

#--------------------------------------------------------------------#
# Variables                                                          #
#--------------------------------------------------------------------#
@LoSDAttr = ();
%HoSDDefs = ();
@LoCAttr = ();
%HoCAttr = ();
@LoCMgrAttr = ();
%HoCMgrAttr = ();
@LoPAttr = ();
%HoPAttr = ();
@LoDAttr = ();
%HoDAttr = ();

#--------------------------------------------------------------------#
# Main Code                                                          #
#--------------------------------------------------------------------#

# look for the old -a option for attributes and change it to -A
@ARGV = translate_lsAOpt(@ARGV);

# parse the command line, exit if there are errors 
my ($rc, $resource, $req_properties, @attributes) = &parse_cmd_line;
($rc == 0) || error_exit($rc);

# initialize a session with RMC
($rc, $session) = init_session();
($rc == 0) || error_exit($rc);
$Cleanup{Session} = $session;

# if no resource names specified display the list of resource
# names.
if (!$resource) {               # No resource operand
    # List the Resource Class Names

    # Need a Response Class
    $response = CT::MC::qdef_rsrc_class_rsp_t->new;

    # Let this subroutine handle the real call to the extension
    # and dealing with all of the return codes..
    $rc = qdef_resource_class($session, "", $response, $Opt_Exp_Desc);
    ($rc == 0) || error_exit($rc); 
    
    # Display the Resource Class Definitions
    $rc = display_resource_class_names($response, $Opt_No_HDR, 
        $Opt_Long_Format, 0, $Opt_Delm_Format, $Opt_Delm_Str);
    ($rc == 0) || error_exit($rc);
}

elsif ($Opt_SD_Def) {
    # List the Structured Data Definition

    # Need a Response Class
    $response = CT::MC::qdef_sd_rsp_t->new;

    # Select the attributes that are SDs and that at least one of the
    # requested properties or were in the list of attributes 
    # specified on the command line.    
    $rc = select_SD_attr($session, $resource, $req_properties, 
        \@attributes);
    ($rc == 0) || error_exit($rc);

    # If there are any SD attributes to be displayed 
    # let the subroutine make the call to the extension, and 
    # handle all the assorted potential errors.
    if (scalar(@attributes) > 0) {
        $rc = qdef_sd($session, $resource, \@attributes, $response);
        ($rc == 0) || error_exit($rc);

        # Get response for valid values if they were requested by user.
        # Call subroutine to handle valid values extension.
        if ($Opt_Valid_Vals) {
            
            my $usage = $Opt_LS_PAttr ? MC_VV_USAGE_PATTR_RESOURCE
                                      : MC_VV_USAGE_DATTR_RESOURCE;

            if ($Opt_LS_Class) {
                $usage = $Opt_LS_PAttr ? MC_VV_USAGE_PATTR_RSRC_CLASS
                                       : MC_VV_USAGE_DATTR_RSRC_CLASS;
            }

            $response_vv = CT::MC::qdef_valid_vals_rsp_t->new;
            $rc = qdef_valid_vals($session, $resource, \@attributes,
                                  $response_vv, $usage);
            ($rc == 0) || error_exit($rc);
        }
        # Format the Class Query Definition Attributes into
        # a form suitable for display.
        format_sd_defs($resource, $response, \@attributes, 
            \@LoSDAttr, \%HoSDDefs, $response_vv);
    }

    # Display the Resource Persistent Attributes Defs & Desc
    $rc = display_sd_defs($resource, \@LoSDAttr, \%HoSDDefs);
    ($rc == 0) || error_exit($rc);
}

elsif ($Opt_LS_Class_Def) {
    # List the Resource Class Definition

    # Need a Response Class
    $response = CT::MC::qdef_rsrc_class_rsp_t->new;
    
    # Let the subroutine make the call to the extension, and
    # handle all the assorted potential errors.
    $rc = qdef_resource_class($session, $resource, $response, 
        $Opt_Exp_Desc);
    ($rc == 0) || error_exit($rc); 

    # Format the Class Query Definition Attributes into
    # a form suitable for display.
    format_class_attributes($resource, $response, \@LoCAttr, 
        \%HoCAttr, \@LoCMgrAttr, \%HoCMgrAttr);

    # Display the Resource Persistent Attributes Defs & Desc
    ($Opt_No_HDR) || 
        printIMsg("IMsglsrsrcdefLsRsrcClassDefHdr", $resource);
    my $row_title = "resource class";
    @attributes = ();
    $rc = display_attributes("", $row_title, \@attributes,
        \@LoCAttr, \%HoCAttr); 
    ($rc == 0) || error_exit($rc);

    $row_title = "rsrc_mgrs";
    @attributes = ();
    $rc = display_attributes("", $row_title, \@attributes, 
        \@LoCMgrAttr, \%HoCMgrAttr);
    ($rc == 0) || error_exit($rc);
} 

elsif ($Opt_LS_Input_File) {
    # Listing Input File for mkrsrc or chrsrc 

    # Need a Response for Persistent Attributes
    $response = CT::MC::qdef_pattr_rsp_t->new;

    # Get the persistent attribute definitions.
    # Let the subroutine make the call to the extension, and
    # handle all the assorted potential errors.
    $rc = qdef_p_attribute($session, $resource, \@attributes,
        $response);
    ($rc == 0) || error_exit($rc);

    # Format the Query Definition Persistent Attributes into
    # a form suitable for display. Filter out any attributes
    # that don't have one of the specified properties.
    # Attributes listed on command lide override property filtering.
    format_p_attr_for_input($resource, $response, $req_properties,
        \@attributes, \@LoPAttr, \%HoPAttr);

    # Display the Resource Persistent Attributes Defs & Desc
    (!$Opt_No_HDR && $Opt_LS_Class) &&
        print "PersistentResourceClassAttributes::\n"; 
    (!$Opt_No_HDR && !$Opt_LS_Class) &&
        print "PersistentResourceAttributes::\n";
    my $row_title = "resource";
    @attributes = ();
    $rc = display_attributes("", $row_title, \@attributes,
         \@LoPAttr, \%HoPAttr);
    ($rc == 0) || error_exit($rc);
}

elsif ($Opt_LS_PAttr) {
    # Listing Resource Class or Resource Persistent Attribute Defs

    # Need a Response for Persistent Attributes
    $response = CT::MC::qdef_pattr_rsp_t->new;

    # Get response for valid values if they were requested by user.
    # Call subroutine to handle valid values extension.
    if ($Opt_Valid_Vals) {
        $response_vv = CT::MC::qdef_valid_vals_rsp_t->new;
        my $usage = $Opt_LS_Class ? MC_VV_USAGE_PATTR_RSRC_CLASS
                                  : MC_VV_USAGE_PATTR_RESOURCE; 

        $rc = qdef_valid_vals($session, $resource, \@attributes,
                              $response_vv, $usage);
        ($rc == 0) || error_exit($rc);
    }

    # Let the subroutine make the call to the extension, and
    # handle all the assorted potential errors.
    $rc = qdef_p_attribute($session, $resource, \@attributes,
                           $response);
    ($rc == 0) || error_exit($rc);

    # Format the Query Definition Persistent Attributes into
    # a form suitable for display. Filter out any attributes
    # that don't have one of the specified properties. 
    # Attributes listed on command lide override property filtering.
    format_p_attributes($resource, $response, $req_properties, 
        \@attributes, \@LoPAttr, \%HoPAttr, $response_vv);

    # Display the Resource Persistent Attributes Defs & Desc
    (!$Opt_No_HDR && $Opt_LS_Class) &&   
        printIMsg("IMsglsrsrcdefLsRsrcClassPAttrDefHdr", $resource);
    (!$Opt_No_HDR && !$Opt_LS_Class) &&
        printIMsg("IMsglsrsrcdefLsRsrcPAttrDefHdr", $resource);
    my $row_title = "attribute";
    @attributes = ();
    $rc = display_attributes("", $row_title, \@attributes,
         \@LoPAttr, \%HoPAttr); 
    ($rc == 0) || error_exit($rc);
}

elsif ($Opt_LS_DAttr) {
    # Listing Resource Dynamic Attribute Definitions

    # Need a Response for Dynamic Attributes
    $response = CT::MC::qdef_dattr_rsp_t->new;

    # Let the subroutine make the call to the extension, and
    # handle all the assorted potential errors.
    $rc = qdef_d_attribute($session, $resource, \@attributes, 
        $response);
    ($rc == 0) || error_exit($rc);

    # Get response for valid values if they were requested by user.
    # Call subroutine to handle valid values extension.
    if ($Opt_Valid_Vals) {
        $response_vv = CT::MC::qdef_valid_vals_rsp_t->new;
        my $usage = $Opt_LS_Class ? MC_VV_USAGE_DATTR_RSRC_CLASS
                                  : MC_VV_USAGE_DATTR_RESOURCE;
        
        $rc = qdef_valid_vals($session, $resource, \@attributes,
                              $response_vv, $usage);
        ($rc == 0) || error_exit($rc);
    }

    # Format the Query Definition Dynamic Attributes into
    # a form suitable for display. Filter out any attributes
    # that don't have one of the specified properties. 
    # Attributes listed on command lide override property filtering.
    format_d_attributes($resource, $response, $req_properties,
        \@attributes, \@LoDAttr, \%HoDAttr, $response_vv);

    # Display the Resource Dynamic Attributes Defs & Desc
    (!$Opt_No_HDR && $Opt_LS_Class) &&
        printIMsg("IMsglsrsrcdefLsRsrcClassDAttrDefHdr", $resource);
    (!$Opt_No_HDR && !$Opt_LS_Class) &&
        printIMsg("IMsglsrsrcdefLsRsrcDAttrDefHdr", $resource);
    my $row_title = "attribute";
    @attributes = ();
    $rc = display_attributes("", $row_title, \@attributes,
         \@LoDAttr, \%HoDAttr);
    ($rc == 0) || error_exit($rc);
}

if ($response->array_count > 0) {
    $rc = CT::MC::free_response($response);
    ($rc == 0) || exit $rc;
}

if (defined($response_vv) && ($response_vv->array_count > 0)) {
    $rc = CT::MC::free_response($response_vv);
    ($rc == 0) || exit $rc;
}

# Cleanup 
$rc = term_session($session);
exit $rc;


#--------------------------------------------------------------------#
# End Main Code                                                      #
#--------------------------------------------------------------------#


#--------------------------------------------------------------------#
# parse_cmd_line - Parse the command line for options and operands.  #
#   Set appropriate global variables as outlined below, make sure we #
#   have a valid combination of arguments / options.                 #
#                                                                    #
# Return:                                                            #
#   $rc   0                  Command line parsed fine, no problem.   #
#         SR_CLI_BAD_FLAG    Command line contained a bad flag.      #
#   $resource                Resource Class Name.                    #
#   $properties              Attributes having these properties      #
#                            should be displayed.                    #
#   @attributes              Array of attribute names.               #
#                                                                    #
# Global Variables Modified:                                         #
#   $Opt_Current       output   True (-c) print current cluster info #
#   $Opt_Exp_Desc      output   True (-e) print both definition      #
#                               and description (print all).         #
#   $Opt_LS_Class_Def  output   True (-c) display the resource class #
#                               definition this is not the same as   #
#                               combining -Ap and -c.                #
#   $Opt_SD_Def        output   True (-s) display the detailed       #
#                               structured data definition for a     #
#                               attr defined as an SD.               #
#   $Opt_LS_Input_File output   True (-i) create/list an input file  #
#                               suitable for mkrsrc or chrsrc.       #
#   $Opt_LS_Class      output   True (c) display the resource        #
#                               class pers or dynamic definition.    #
#   $Opt_LS_DAttr      ouptput  True (-A d) display the resource     #
#                               dynamic attributes.                  #
#   $Opt_LS_PAttr      output   True (-A p) display the resource     #
#                               persistent attributes.               #
#   $Opt_Valid_Vals    output   True (-v) display valid values.      #
#   $Opt_Long_Format   output   True (-l) print one entry per line   #
#   $Opt_Table_Format  output   True (-t) table format.              #
#   $Opt_Delm_Format   output   True (-d|-D) print delimiter         #
#                               separated output.                    #
#   $Opt_Delm_Str      output   the string to use as the delimiter,  #
#                               default is colon (:).                #
#   $Opt_No_HDR        output   True (-x) print without header       #
#   $Verbose           output   True (-V) turn Verbose mode on.      #
#   $Trace             output   True (-T) turn Trace mode on.        #
#--------------------------------------------------------------------#
sub parse_cmd_line 
{
my(@original_argv) = @ARGV;
my @attributes = ();
my %opts = ();

# Process the command line...
#if (!&getopts('ha:ceip:sdD:ltxvVT', \%opts)) { # Gather options/flags
if (!&getopts('hA:ceip:sdD:ltxVT', \%opts)) { # Gather options/flags
    &print_usage;                       # display proper usage
    return MC_CLI_BAD_FLAG;             # return bad rc - bad flag 
}

# Always accept the -h help flag regardless of other flags or operands
if (defined $opts{h}) {                 # -h, help request  
    &print_usage;                       # print usage statement
    exit(0);                            # all done with good return!
}

# If no operands in lsrsrcdef that is OK, it just means display
# a list of all Resource Class Names

# Get the arguments (operands)
if ($#ARGV >= 0) { 
    $resource = shift @ARGV;            # user specified resource
    @attributes = @ARGV;                # array of attribute names
}

# See which options/flags were used...

if (defined $opts{A}) {                 # -A, attribute type
    if ($opts{A} eq "d") {              # -A d, dynamic attributes
        $Opt_LS_DAttr = $TRUE;
        $Opt_LS_PAttr = $FALSE;
    }
    elsif ($opts{A} eq "p") {           # -A p, persistent attributes
        $Opt_LS_PAttr = $TRUE;
    }
    else {
        # -A flag requires d dynamic | p persistent
        printCEMsg("EMsgMCcliImproperUsageFlag", "-A $opts{A}");
        $rc = MC_CLI_BAD_FLAG;
        return($rc, $resource);
    }
}

# The resource class definition is a separate definition,
# it is not the same as the resource class persistent or dynamic 
# attribute definition
if (defined $opts{c}) {                 # -c, rsrc class definitions
    if (defined $opts{A}  || defined $opts{s}) {
        $Opt_LS_Class = $TRUE;
    }
    else {
        $Opt_LS_Class_Def = $TRUE;
        $Opt_LS_PAttr = $FALSE;
    }
}

if (defined $opts{e}) {                 # -e, display all desc & def
    $Opt_Exp_Desc = $TRUE;
}

if (defined $opts{i}) {
    $Opt_LS_Input_File = $TRUE;
    # Default to displaying only required for define and optional for 
    # define attributes. User should enter -p <property> if they want
    # other properties.
    $properties = MC_RSRC_PATTR_REQD_FOR_DEFINE | 
        MC_RSRC_PATTR_OPTION_FOR_DEFINE;    
    # -i overrides -Ad (-i only makes sense with persistent attrs)
    if (defined $opts{A} && $opts{A} eq "d") {
        $Opt_LS_DAttr = $FALSE;
        $Opt_LS_PAttr = $TRUE;
    }
    if (defined $opts{c}) {
        $Opt_LS_Class_Def = $FALSE;
        $Opt_LS_Class = $TRUE;
    }
}

if (defined $opts{p}) {                 # -p Property
    $properties = $opts{p};
    # Make sure properties is a number (hex, octal or decimal)
    if ($properties !~ /^(0x|\d+)\d*/) {
        printCEMsg("EMsgMCcliImproperUsageFlag", "-p $opts{p}");
        &print_usage;
        return MC_CLI_USER_ERROR;
    }
    # Convert properties specified in hex or octal to decimal
    $properties = oct $properties if $properties =~ /^0/;

    # Just some mininmal range checking - valid property values only
    # range between 0x0001 to 0x0020 but allow for growth here
    # -p 0 means display attributes with any property
    if ($properties < hex("0x0000") || $properties > hex("0xFFFF")) {
        printCEMsg("EMsgMCcliImproperUsageFlag", "-p $opts{p}");
        &print_usage;
        return MC_CLI_USER_ERROR;
    }
    if ($properties == 0) {
        $properties = hex("0xFFFF");
    }
}
elsif (!defined $opts{i}) {
    # Default to display only public attributes
    # Dynamic and Persistent Public properties are both 0x0020
    $properties = MC_RSRC_PATTR_PUBLIC;   # Default to Public 
}

# The -i flag overrides -s
if (defined $opts{s} && !defined $opts{i}) { # -s, sd definitions
    $Opt_SD_Def = $TRUE;
}

# The -i flag overrides -v
if (defined $opts{v} && !defined $opts{i}) { # -v valid values 
    $Opt_Valid_Vals = $TRUE;
}

# The -l flag overrides -t which overrides -d which overrides -D flag
# When -i flag always display in long format
if (defined $opts{l} || defined $opts{i}) { # -l long format, 
    $Opt_Long_Format = $TRUE;          #    1 entry/line
}
elsif (defined $opts{t}) {             # -t tabular format
    $Opt_Table_Format = $TRUE;
    $Opt_Long_Format = $FALSE;
}
elsif (defined $opts{d}) {             # -d delimiter format
    $Opt_Delm_Format = $TRUE;
    $Opt_Long_Format = $FALSE; 
}
elsif (defined $opts{D}) {             # -D <delimiter> format
    $Opt_Delm_Format = $TRUE;
    $Opt_Long_Format = $FALSE;
    $Opt_Delm_Str = $opts{D};
}

if (defined $opts{x}) {                # -x do not print header
    $Opt_No_HDR = $TRUE;
}

if (defined $opts{T}) {                # -T trace
    $Trace = $TRUE; 
}

if (defined $opts{V}) {                # -V verbose 
    $Verbose = $TRUE;
}

return(0, $resource, $properties, @attributes); # success
}   # end parse_cmd_line


#--------------------------------------------------------------------#
# print_usage : print the usage statement (syntax) to stdout.        #
#   See this command's prologue syntax section for current usage.    #
#--------------------------------------------------------------------#
sub print_usage
{
printIMsg("IMsglsrsrcdefUsage25");
}   # end print_usage


#--------------------------------------------------------------------#
# qdef_p_attribute - function to call the CT::MC::qdef_p_attribute_  #
#   bp extension and handle possible errors.                         #
#                                                                    #
# Parameters:                                                        #
#   $session          input   RMC session handle.                    #
#   $resource         input   Name of the resource class whose attr  #
#                             definitions we want.                   #
#   @$r_attributes    input   Reference to array of attribute names. #
#   $response         in/out  Response data structure, on output     #
#                             this will point to the real resposne.  #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_Exp_Desc     input  TRUE if display def & description.      #
#   $Opt_LS_Class     input  TRUE if display resource class pers def #
#                            versus the resource pers def.           #
#--------------------------------------------------------------------#
sub qdef_p_attribute 
{
my ($session, $resource, $r_attributes, $response) = @_;
my $rc = 0;
 
my $error = CT::MC::errnum_t->new;

my $options = $Opt_Exp_Desc ? MC_QDEF_OPTS_NONE : MC_QDEF_OPTS_NODSCRP;

my $attr_count = scalar(@$r_attributes); 

$Trace && print STDERR "Calling CT::MC::qdef_p_attribute_bp\n";

$rc = CT::MC::qdef_p_attribute_bp($session, $response, $error,
                                $options, $resource, $Opt_LS_Class,
                                $r_attributes, $attr_count);

$Trace && print STDERR "Return  CT::MC::qdef_p_attribute_bp\n";

$rc = error_check("mc_qdef_p_attribute_bp", $resource, $response, 
    $rc, $error);

return $rc;
}   # end qdef_p_attribute


#--------------------------------------------------------------------#
# qdef_valid_vals - function to call the CT::MC::qdef_valid_         #
#   values_bp extension.                                             #
#                                                                    #
# Parameters:                                                        #
#   $session          input   RMC session handle.                    #
#   $resource         input   Name of the resource class whose attr  #
#                             definitions we want.                   #
#   @$r_attributes    input   Reference to array of attribute names. #
#   $response         in/out  Response data structure, on output     #
#                             this will point to the real resposne.  #
#   $usage            input   One of mc_vv_usage_t enum types.       #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_Exp_Desc     input   TRUE if display def & description.     #
#                                                                    #
#TODO: While support for retrieving valid values through action      #
#      invokation is documented in the API, as of 8/6/01, it has not # 
#      yet been implemented. Once it is implemented in the RMC C API,# 
#      support for retrieving valid values using actions should be   # 
#      added to this command.                                        # 
#--------------------------------------------------------------------#
sub qdef_valid_vals
{
my ($session, $resource, $r_attributes, $response, $usage) = @_;
my $rc = 0;
 
my $error = CT::MC::errnum_t->new;

my $options = $Opt_Exp_Desc ? MC_QDEF_OPTS_NONE : MC_QDEF_OPTS_NODSCRP;

my $attr_count = scalar(@$r_attributes); 

$Trace && print STDERR "Calling CT::MC::qdef_valid_values_bp\n";

$rc = CT::MC::qdef_valid_values_bp($session, $response, $error,
                                   $options, $resource, $usage,
                                   $r_attributes, $attr_count);

$Trace && print STDERR "Return  CT::MC::qdef_valid_values_bp\n";

$rc = error_check("mc_qdef_valid_values_bp", $resource, $response, 
    $rc, $error);

return $rc;
}   # end qdef_valid_vals


#--------------------------------------------------------------------#
# qdef_d_attribute - function to call the CT::MC::qdef_d_attribute_  #
#   bp extension and handle possible errors.                         #
#                                                                    #
# Parameters:                                                        #
#   $session          input   RMC session handle.                    #
#   $resource         input   Name of the resource class whose attr  #
#                             definitions we want.                   #
#   @$r_attributes    input   Reference to array of attribute names. #
#   $response         in/out  Response data structure, on output     #
#                             this will point to the real resposne.  #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_Exp_Desc     input   TRUE if display def & description.     #
#   $Opt_LS_Class     input   TRUE if display resource class dyna    #
#                             def versus the resource dyna def.      #
#--------------------------------------------------------------------#
sub qdef_d_attribute 
{
my ($session, $resource, $r_attributes, $response) = @_;
my $rc = 0;
 
my $error = CT::MC::errnum_t->new;

my $options = $Opt_Exp_Desc ? MC_QDEF_OPTS_NONE : MC_QDEF_OPTS_NODSCRP;

my $attr_count = scalar(@$r_attributes);

$Trace && print STDERR "Calling CT::MC::qdef_d_attribute_bp\n";

$rc = CT::MC::qdef_d_attribute_bp($session, $response, $error,
                                $options, $resource, $Opt_LS_Class,
                                $r_attributes, $attr_count);

$Trace && print STDERR "Return  CT::MC::qdef_d_attribute_bp\n";

$rc = error_check("mc_qdef_d_attribute_bp", $resource, $response, 
    $rc, $error);

return $rc;
}   # end qdef_d_attribute


#--------------------------------------------------------------------#
# qdef_sd - function to call the CT::MC::qdef_sd_bp extension and    #
#   handle possible errors.                                          #
#                                                                    #
# Parameters:                                                        #
#   $session          input   RMC session handle.                    #
#   $resource         input   Name of the resource class whose SD    #
#                             definitions we want.                   #
#   @$r_attributes    input   Reference to array of attribute names. #
#   $response         in/out  Response data structure, on output     #
#                             this will point to the real resposne.  #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_Exp_Desc     input   TRUE if display def & description.     #
#   $Opt_LS_Class     input   TRUE if display resource class SD def  #
#                             versus the resource SD def.            #
#   $Opt_LS_PAttr     input   TRUE if display persistent attr.       #
#   $Opt_LS_DAttr     input   TRUE if display dynamic attributes.    #
#--------------------------------------------------------------------#
sub qdef_sd
{
my ($session, $resource, $r_attributes, $response) = @_;
my $rc = 0;
 
my $error = CT::MC::errnum_t->new;

my $options = $Opt_Exp_Desc ? MC_QDEF_OPTS_NONE : MC_QDEF_OPTS_NODSCRP;

my $sd_use = MC_SD_USAGE_PATTR_RESOURCE;
if ($Opt_LS_Class) {
    $sd_use = MC_SD_USAGE_PATTR_RSRC_CLASS;
    if ($Opt_LS_DAttr) {
        $sd_use = MC_SD_USAGE_DATTR_RSRC_CLASS;
    }
}
else {
    if ($Opt_LS_DAttr) {
        $sd_use = MC_SD_USAGE_DATTR_RESOURCE;
    }
}

my $attr_count = scalar(@$r_attributes);

$Trace && print STDERR "Calling CT::MC::qdef_sd_bp\n";

$rc = CT::MC::qdef_sd_bp($session, $response, $error,
                         $options, $resource, $sd_use, 
                         $r_attributes, $attr_count);

$Trace && print STDERR "Return  CT::MC::qdef_sd_bp\n";

$rc = error_check("mc_qdef_sd_bp", $resource, $response, $rc, $error);

return $rc;
}   # end qdef_sd


#--------------------------------------------------------------------#
# select_SD_attr - function to determine which attributes are        #
#   structured data type (ct_sd_ptr or ct_sd_ptr_array). Also        #
#   determines which SD attributes have at least one of the          #
#   specified properties or was listed on the command line.          #
#                                                                    #
# Parameters:                                                        #
#   $session          input   RMC session handle.                    #
#   $resource         in      Resource class name.                   #
#   $req_properties   in      Return attributes with these props.    #
#   @$r_attr_names    in/out  Reference to list of attributes        #
#                             On input attributes from command line  #
#                             (if any).                              #
#                             On output filtered list of attr names. #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_LS_Class     input   TRUE if display resource class versus  #
#                             the resource.                          #
#   $Opt_LS_PAttr     input   TRUE if display persistent attributes. #
#   $Opt_LS_DAttr     input   TRUE if display dynamic attributes.    #
#--------------------------------------------------------------------#
sub select_SD_attr
{
my ($session, $resource, $req_properties, $r_attr_names) = @_;

my @LoAttrDefs = ();                   # Attr Names, the key
                                       # in HoAttrDefs in rsp order
my %HoAttrDefs = ();                   # Complex Hash of 
                                       # attr names and definitions

my @req_attributes = ();               # Required / filtered attrs
my $attribute;
my $rc = 0;

# Get the attribute definitions filtering out any attribute that 
# does not have one of the specified properties unless it is in the
# list of required attributes. Also verifies the attr names are valid.
if ($Opt_LS_PAttr) {
    $rc = get_p_attr_defs($session, $resource, $Opt_LS_Class,
        $req_properties, $r_attr_names, \@LoAttrDefs, \%HoAttrDefs);
    ($rc == 0) || return($rc);
}

if ($Opt_LS_DAttr) {
    $rc = get_d_attr_defs($session, $resource, $Opt_LS_Class,
        $req_properties, $r_attr_names, \@LoAttrDefs, \%HoAttrDefs);
    ($rc == 0) || return($rc);
}

# Filter out any attribute with a data type other than 
# ct_sd_ptr or ct_sd_ptr_array.
foreach $attribute (@LoAttrDefs) {
    if (($HoAttrDefs{$attribute}{at_dtype} == CT_SD_PTR) ||
        ($HoAttrDefs{$attribute}{at_dtype} == CT_SD_PTR_ARRAY)) {
        push @req_attributes, $attribute;
    }           
    else {
        delete $HoAttrDefs{$attribute};
    }
}   

# Push the list of required attributes after filtering onto 
# the list of attributes that will be displayed
# If any attributes were specified on the command line they 
# override the filtered list of required attributes
if (scalar(@$r_attr_names) == 0) {
    foreach $attribute (@req_attributes) {
        push @$r_attr_names, $attribute;
    }   
}

return $rc;
}   # end select_SD_attr


#--------------------------------------------------------------------#
# format_class_attributes - formats the resource class attributes    #
#   into a complex hash of attribute elements %rHoAttr) which can    #
#   then be easily displayed using utility display_resource_data.    #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Response data structure.               #
#   @$rLoCAttr        in/out  Reference to the list of class defn    #
#                             attributes that are also in HoCAttr.   #
#   %$rHoCAttr        in/out  Reference to the hash of class defn    #
#                             attributes.                            #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub format_class_attributes 
{
my($resource, $response, $rLoCAttr, $rHoCAttr, 
    $rLoCMgrAttr, $rHoCMgrAttr) = @_;

my($name, $r, $j);

# format each of the attribute in the response structure so 
# can use more generic printing....
my %HoRspAttr = ( 
    "class_name"            => 1,
    "class_id"              => 1,
    "properties"            => 1,
    "display_name"          => 1,
    "description"           => 1,
    "locator"               => 1,
    "class_pattr_count"     => 1,
    "class_dattr_count"     => 1,
    "class_action_count"    => 1,
    "pattr_count"           => 1,
    "dattr_count"           => 1,
    "action_count"          => 1,
    "error_count"           => 1,
    "rsrc_mgrs"             => 1,
    "rsrc_mgr_count"        => 1
);  

# Hash of Hash of mc_rsrc_mgr_t attributes 
my %HoMgrAttr = (
    "mgr_name"              => 1, 
    "first_key"             => 1,
    "last_key"              => 1
);

my %elements = ();
my $attribute = CT::MC::attribute_t->new;
$response_cnt = $response->array_count;
# Even though I have a foreach loop here there should only be 1 
# response since we only asked for 1 class definition on the
# qdef_resource_class call.
for ($r = 0; $r < $response_cnt; $r++) {
    if ($HoRspAttr{"class_name"}) {
        %elements = ();
        $elements{at_name} = "class_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->class_name($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"class_id"}) {
        %elements = ();
        $elements{at_name} = "class_id";
        $elements{at_dtype} = CT_UINT32;   # Really a CT_UINT16
        $elements{at_value} = $response->class_id($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"properties"}) {
        %elements = ();
        $elements{at_name} = "properties";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_properties($response->properties($r), "class");
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"display_name"}) {
        %elements = ();
        $elements{at_name} = "display_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->display_name($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"description"}) {
        %elements = ();
        $elements{at_name} = "description";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->description($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"locator"}) {
        %elements = ();
        $elements{at_name} = "locator";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->locator($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"class_pattr_count"}) {
        %elements = ();
        $elements{at_name} = "class_pattr_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->class_pattr_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"class_dattr_count"}) {
        %elements = ();
        $elements{at_name} = "class_dattr_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->class_dattr_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"class_action_count"}) {
        %elements = ();
        $elements{at_name} = "class_action_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->class_action_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"pattr_count"}) {
        %elements = ();
        $elements{at_name} = "pattr_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->pattr_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"dattr_count"}) {
        %elements = ();
        $elements{at_name} = "dattr_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->dattr_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"action_count"}) {
        %elements = ();
        $elements{at_name} = "action_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->action_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"error_count"}) {
        %elements = ();
        $elements{at_name} = "error_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->error_count($r);
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    $rsrc_mgr_count = $response->rsrc_mgr_count($r);
    if ($HoRspAttr{"rsrc_mgr_count"}) {
        %elements = ();
        $elements{at_name} = "rsrc_mgr_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $rsrc_mgr_count;
        build_HoAttr($elements{at_name}, $rLoCAttr, $rHoCAttr, \%elements, $r);
    }

    if ($HoRspAttr{"rsrc_mgrs"}) {
        for ($j = 0; $j < $rsrc_mgr_count; $j++) {
            if ($HoMgrAttr{"mgr_name"}) {
                %elements = ();
                $elements{at_name} = "mgr_name";
                $elements{at_dtype} = CT_CHAR_PTR;
                $elements{at_value} = $response->mgr_name($r, $j);
                build_HoAttr($elements{at_name}, $rLoCMgrAttr,
                    $rHoCMgrAttr, \%elements, $j);
            }
            if ($HoMgrAttr{"first_key"}) {
                %elements = ();
                $elements{at_name} = "first_key";
                $elements{at_dtype} = CT_UINT32;
                $elements{at_value} = $response->first_key($r, $j);   
                build_HoAttr($elements{at_name}, $rLoCMgrAttr,
                    $rHoCMgrAttr, \%elements, $j);
            }
            if ($HoMgrAttr{"last_key"}) {
                %elements = ();
                $elements{at_name} = "last_key";
                $elements{at_dtype} = CT_UINT32;
                $elements{at_value} = $response->last_key($r, $j);   
                build_HoAttr($elements{at_name}, $rLoCMgrAttr,
                    $rHoCMgrAttr, \%elements, $j);
            }
        }
    }

}   # end for responses

return;
}   # end of format_class_attributes


#--------------------------------------------------------------------#
# format_p_attr_for_input - formats the persistent attributes into   #
#   an input format suitable for mkrsrc or chrsrc. Formats the       #
#   persistent attributes into a complex hash of attribute elements  #
#   which can then be easily displayed using utility                 #
#   dislay_resouce_data.                                             #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Response data structure.               #
#   $req_properties   input   Requested properties - only put the    #
#                             attributes in the hash that have these #
#                             requested properties.                  #
#   @$r_attributes    input   Reference to the list of attributes    #
#                             to be displayed, if empty display all  #
#                             attributes.                            #
#   @$rLoPAttr        in/out  Reference to the list of persistent    #
#                             attributes that are also in HoPAttr.   #
#   %$rHoPAttr        in/out  Reference to the hash of persistent    #
#                             attributes.                            #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub format_p_attr_for_input
{
my($resource, $response, $req_properties, $r_attributes,
    $rLoPAttr, $rHoPAttr) = @_;

my($attr_name, $r);

# format each of the attribute in the response structure so
# can use more generic printing....

my %elements = ();
my $response_cnt = $response->array_count;
my $attribute = CT::MC::attribute_t->new();
for ($r = 0; $r < $response_cnt; $r++) {

    # Filter out the attributes that should not be displayed
    # Attributes requested as operand to this command always get
    # displayed ($r_attributes), otherwise display any attribute
    # that has one of the requested properties.
    (required_attr($response->program_name($r),
        $response->properties($r), $r_attributes, $req_properties)) ||
        next;

    # Filter out attributes that have already been processed
    $attr_name = $response->program_name($r);
    (exists $rHoPAttr->{$attr_name}) && next;

    %elements = ();
    $elements{at_name}  = $attr_name; 
    $elements{at_id}    = $response->attribute_id($r);
    $elements{at_dtype} = CT_CHAR_PTR;
    $elements{at_value} = 
        data_type_to_string($response->data_type($r));
    build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, 0);

}   # end for responses

return;
}   # end of format_p_attr_for_input



#--------------------------------------------------------------------#
# format_p_attributes - formats the persistent attributes into a     #
#   complex hash of attribute elements (%rHoAttr) which can then     #
#   be easily displayed using utility dislay_resouce_data.           #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Response data structure.               #
#   $req_properties   input   Requested properties - only put the    #
#                             attributes in the hash that have these #
#                             requested properties.                  #
#   @$r_attributes    input   Reference to the list of attributes    #
#                             to be displayed, if empty display all  #
#                             attributes.                            #
#   @$rLoPAttr        in/out  Reference to the list of persistent    #
#                             attributes that are also in HoPAttr.   #
#   %$rHoPAttr        in/out  Reference to the hash of persistent    #
#                             attributes.                            #
#   $response_vv      input   Valid values response structure.       #
#                                                                    #
# Global References:                                                 #
#   $Opt_Valid_Vals   input   True if valid values are being         #
#                             displayed.                             #
#--------------------------------------------------------------------#
sub format_p_attributes
{
my($resource, $response, $req_properties, $r_attributes, 
    $rLoPAttr, $rHoPAttr, $response_vv) = @_;

my($name, $r);

# format each of the attribute in the response structure so
# can use more generic printing....

# List of field names in the qdef_pattr_rsp_t
my %HoRspAttr = (
    "program_name"      => 1,
    "display_name"      => 1,
    "group_name"        => 1,
    "properties"        => 1,
    "description"       => 1,
    "attribute_id"      => 1,
    "group_id"          => 1,
    "data_type"         => 1,
    "variety_list"      => 1,
    "variety_count"     => 1,
    "default_value"     => 1,
    "valid_vals"        => $Opt_Valid_Vals,
    "valid_vals_label"  => $Opt_Valid_Vals
);

my %elements = ();
my $response_cnt = $response->array_count;
my $attribute = CT::MC::attribute_t->new();
my $a = 0;
for ($r = 0; $r < $response_cnt; $r++) {

    # Filter out the attributes that should not be displayed
    # Attributes requested as operand to this command always get
    # displayed ($r_attributes), otherwise display any attribute
    # that has one of the requested properties.
    (required_attr($response->program_name($r), 
        $response->properties($r), $r_attributes, $req_properties)) ||  
        next;   

    if ($HoRspAttr{"program_name"}) {
        %elements = ();
        $elements{at_name} = "program_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->program_name($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }
    
    if ($HoRspAttr{"display_name"}) {
        %elements = ();
        $elements{at_name}  = "display_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->display_name($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"group_name"}) {
        %elements = ();
        $elements{at_name} = "group_name";
        $elements{at_dtype} = CT_CHAR_PTR;    
        $elements{at_value} = $response->group_name($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"properties"}) {
        %elements = ();
        $elements{at_name} = "properties";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_properties($response->properties($r), "pattr");
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"description"}) {
        %elements = ();
        $elements{at_name} = "description";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->description($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }
    
    if ($HoRspAttr{"attribute_id"}) {
        %elements = ();
        $elements{at_name} = "attribute_id";
        $elements{at_dtype} = CT_INT32;
        $elements{at_value} = $response->attribute_id($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"group_id"}) {
        %elements = ();
        $elements{at_name} = "group_id";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->group_id($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    $data_type = $response->data_type($r);
    if ($HoRspAttr{"data_type"}) {
        %elements = ();
        $elements{at_name} = "data_type";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = data_type_to_string($data_type);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"variety_list"}) {
        %elements = ();
        $elements{at_name} = "variety_list";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_variety_list($response, $r, 
                $response->variety_count($r)); 
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"variety_count"}) {
        %elements = ();
        $elements{at_name} = "variety_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->variety_count($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"default_value"}) {
        %elements = ();
        $elements{at_name} = "default_value";
        $elements{at_dtype} = $data_type;
        $elements{at_value} = $response->default_value($r);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }
 
    #  TODO: Do we want a valid values field present at all times? 
    #        (Or just there when "-v" flag is given, as is the case now?)

    if ($HoRspAttr{"valid_vals"}) {
        %elements = ();
        $elements{at_name} = "valid_vals";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_valid_values($response_vv, $r, $response_vv->count($r),
                                 $data_type);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    if ($HoRspAttr{"valid_vals_label"}) {
        %elements = ();
        $elements{at_name} = "valid_vals_label";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_valid_values_label($response_vv, $r,
                                       $response_vv->count($r), $data_type);
        build_HoAttr($elements{at_name}, $rLoPAttr, $rHoPAttr, \%elements, $a);
    }

    $a = $a + 1;
}   # end for responses

return;
}   # end of format_p_attributes


#--------------------------------------------------------------------#
# format_d_attributes - formats the dynamic attributes into a        #
#   complex hash of attribute elements (%rHoAttr) which can then     #
#   be easily displayed using utility display_resource_data.         #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Response data structure.               #
#   $req_properties   input   Requested properties - only put the    #
#                             attributes in the hash that have these #
#                             requested properties.                  #
#   @$r_attributes    input   Reference to the list of attributes    #
#                             to be displayed, if empty display all  #
#                             attributes.                            #
#   @$rLoDAttr        in/out  Reference to the list of dynamic       #
#                             attributes that are also in HoDAttr.   #
#   %$rHoDAttr        in/out  Reference to the hash of dynamic       #
#                             attributes.                            #
#   $response_vv      input   Valid values response structure.       #
#                                                                    #
# Global References:                                                 #
#   $Opt_Valid_Vals   input  TRUE if attr valid values are being     #
#                            displayed.                              #
#--------------------------------------------------------------------#
sub format_d_attributes
{
my($resource, $response, $req_properties, $r_attributes, 
    $rLoDAttr, $rHoDAttr, $response_vv) = @_;

my($name, $r);

# format each of the attribute in the response structure so
# can use more generic printing....

# List of field names in the qdef_dattr_rsp_t
my %HoRspAttr = (
    "attribute"                 => 1,
    "program_name"              => 1,
    "display_name"              => 1,
    "group_name"                => 1,
    "properties"                => 1,
    "description"               => 1,
    "attribute_id"              => 1,
    "group_id"                  => 1,
    "data_type"                 => 1,
    "variable_type"             => 1,
    "variety_list"              => 1,
    "variety_count"             => 1,
    "init_value"                => 1,
    "min_value"                 => 1,
    "max_value"                 => 1,
    "expression"                => 1,
    "expression_description"    => 1,
    "rearm_expression"          => 1,
    "rearm_description"         => 1,
    "PTX_name"                  => 1,
    "valid_vals"                => $Opt_Valid_Vals,
    "valid_vals_label"          => $Opt_Valid_Vals
);

my %elements = ();
my $attribute = CT::MC::attribute_t->new;
$response_cnt = $response->array_count;
my $a = 0;
for ($r = 0; $r < $response_cnt; $r++) {
    # Filter out the attributes that should not be displayed
    # Attributes requested as operand to this command always get
    # displayed ($r_attributes), otherwise display any attribute
    # that has one of the requested properties.
    (required_attr($response->program_name($r), 
        $response->properties($r), $r_attributes, $req_properties)) ||
        next;   

    if ($HoRspAttr{"program_name"}) {
        %elements = ();
        $elements{at_name} = "program_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->program_name($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"display_name"}) {
        %elements = ();
        $elements{at_name}  = "display_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->display_name($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"group_name"}) {
        %elements = ();
        $elements{at_name} = "group_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->group_name($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"properties"}) {
        %elements = ();
        $elements{at_name} = "properties";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_properties($response->properties($r), "dattr");
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"description"}) {
        %elements = ();
        $elements{at_name} = "description";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->description($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"attribute_id"}) {
        %elements = ();
        $elements{at_name} = "attribute_id";
        $elements{at_dtype} = CT_INT32;
        $elements{at_value} = $response->attribute_id($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"group_id"}) {
        %elements = ();
        $elements{at_name} = "group_id";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->group_id($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    $data_type = $response->data_type($r);
    if ($HoRspAttr{"data_type"}) {
        %elements = ();
        $elements{at_name} = "data_type";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = data_type_to_string($data_type);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"variable_type"}) {
        %elements = ();
        $elements{at_name} = "variable_type";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_variable_type($response->variable_type($r));
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"variety_list"}) {
        %elements = ();
        $elements{at_name} = "variety_list";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_variety_list($response, $r,
                $response->variety_count($r)); 
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"variety_count"}) {
        %elements = ();
        $elements{at_name} = "variety_count";
        $elements{at_dtype} = CT_UINT32;
        $elements{at_value} = $response->variety_count($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"init_value"}) {
        %elements = ();
        $elements{at_name} = "init_value";
        $elements{at_dtype} = $data_type;
        $elements{at_value} = $response->init_value($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"min_value"}) {
        %elements = ();
        $elements{at_name} = "min_value";
        $elements{at_dtype} = $data_type;
        $elements{at_value} = $response->min_value($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"max_value"}) {
        %elements = ();
        $elements{at_name} = "max_value";
        $elements{at_dtype} = $data_type;
        $elements{at_value} = $response->max_value($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"expression"}) {
        %elements = ();
        $elements{at_name} = "expression";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->expression($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"expression_description"}) {
        %elements = ();
        $elements{at_name} = "expression_description";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->expression_description($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"rearm_expression"}) {
        %elements = ();
        $elements{at_name} = "rearm_expression";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->rearm_expression($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"rearm_description"}) {
        %elements = ();
        $elements{at_name} = "rearm_description";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->rearm_description($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"PTX_name"}) {
        %elements = ();
        $elements{at_name} = "PTX_name";
        $elements{at_dtype} = CT_CHAR_PTR;
        $elements{at_value} = $response->PTX_name($r);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"valid_vals"}) {
        %elements = ();
        $elements{at_name} = "valid_vals";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_valid_values($response_vv, $r, $response_vv->count($r),
                                 $data_type);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }

    if ($HoRspAttr{"valid_vals_label"}) {
        %elements = ();
        $elements{at_name} = "valid_vals_label";
        ($elements{at_dtype}, $elements{at_value}) = 
            convert_valid_values_label($response_vv, $r,
                                       $response_vv->count($r), $data_type);
        build_HoAttr($elements{at_name}, $rLoDAttr, $rHoDAttr, \%elements, $a);
    }    

    $a = $a + 1;
}   # end for responses

return;
}   # end of format_d_attributes


#--------------------------------------------------------------------#
# format_sd_defs - formats the structured data definitions for       #
#   resource or resource class dynamic or persistent SD attributes.  #
#   0 or more SDs may have been defined. A complex hash is           #
#   constructed -                                                    #
#      level 1:  Complex hash                                        #
#                key is attribute name (see mc_sd_rsp_t in ct_mc.h)  #
#                data hash of definition data for an SD.             #
#      level 2:  Complex hash                                        #
#                key is field_name (see mc_sd_element_t in ct_mc.h)  #
#                data value                                          #
#      x $rHoSDDefs - to really see what is created.                 #
#      x $$rHoSDDefs{$response->program_name($r)} to see level 2.    #
#      The hash for each attribute (level 2) can be easily displayed #
#      using the MC_cli_display_utils::display_resource_data.        #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Resource Name                          #
#   $response         input   Response data structure.               #
#   @$r_attributes    input   Reference to the list of attributes    #
#                             to be displayed, if empty display all  #
#                             attributes.                            #
#   @$rLoSDAttr       in/out  Reference to the list of SD attributes #
#                             (elements) that are also in HoSDAttr.  #
#   %$rHoSDDefs       in/out  Reference to the hash of SD attributes #
#                             definitions (elements).                #
#   $response_vv      input   Valid values response structure.       #
#                                                                    #
# Global References:                                                 #
#   $Opt_Valid_Vals   input   TRUE if valid values are being         #
#                             displayed.                             #
#--------------------------------------------------------------------#
sub format_sd_defs
{
my($resource, $response, $r_attributes, $rLoSDAttr, $rHoSDDefs,
   $response_vv) = @_;

my %HoSDAttr = ();
my($name, $r);

# format each of the attribute in the response structure so
# can use more generic printing....

# List of field names in the qdef_sd_rsp_t (mc_sd_element_t)
my %HoRspAttr = (
    "element_name"          => 1,
    "display_name"          => 1,
    "description"           => 1,
    "element_data_type"     => 1,
    "element_index"         => 1,
    "valid_vals"            => $Opt_Valid_Vals,
    "valid_vals_label"      => $Opt_Valid_Vals
);

my %elements = ();
my $attribute = CT::MC::attribute_t->new;
$response_cnt = $response->array_count;
for ($r = 0; $r < $response_cnt; $r++) {
    %HoSDAttr = ();
    @$rLoSDAttr = ();
    $element_cnt = $response->element_count($r);  
    for ($e = 0; $e < $element_cnt; $e++) {
        if ($HoRspAttr{"element_name"}) {
            %elements = ();
            $elements{at_name} = "element_name";
            $elements{at_dtype} = CT_CHAR_PTR;
            $elements{at_value} = $response->element_name($r, $e);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr,
                \%elements, 0);
        }

        if ($HoRspAttr{"display_name"}) {
            %elements = ();
            $elements{at_name}  = "display_name";
            $elements{at_dtype} = CT_CHAR_PTR;
            $elements{at_value} = $response->display_name($r, $e);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr,
                \%elements, 0);
        }

        if ($HoRspAttr{"description"}) {
            %elements = ();
            $elements{at_name} = "description";
            $elements{at_dtype} = CT_CHAR_PTR;
            $elements{at_value} = $response->description($r, $e);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr, 
                \%elements, 0);
        }

        if ($HoRspAttr{"element_data_type"}) {
            %elements = ();
            $elements{at_name} = "element_data_type";
            $data_type = $response->element_data_type($r, $e); 
            $elements{at_dtype} = CT_CHAR_PTR;
            $elements{at_value} = data_type_to_string($data_type);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr,
                \%elements, 0);
        }

        my $element_index = $response->element_index($r, $e);
        if ($HoRspAttr{"element_index"}) {
            %elements = ();
            $elements{at_name}  = "element_index";
            $elements{at_dtype} = CT_UINT32;
            $elements{at_value} = $element_index;
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr,
                \%elements, 0);
        } 

        if ($HoRspAttr{"valid_vals"}) {
            %elements = ();
            $elements{at_name} = "valid_vals";
            ($elements{at_dtype}, $elements{at_value}) = 
                convert_sd_valid_values($response_vv, $r,
                                        $response_vv->count($r), $data_type,
                                        $element_index);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr, \%elements,
                         0);
        }

        if ($HoRspAttr{"valid_vals_label"}) {
            %elements = ();
            $elements{at_name} = "valid_vals_label";
            ($elements{at_dtype}, $elements{at_value}) = 
                convert_sd_valid_values_label($response_vv, $r,
                                              $response_vv->count($r), 
                                              $element_index, $data_type);
            build_HoAttr($elements{at_name}, $rLoSDAttr, \%HoSDAttr, \%elements,
                         0);
        }

    } # end for each element
    # Put this SD Attribute definition in the hash with the rest of
    # the SD attributes definitions.
    if ($element_cnt > 0) {
        $$rHoSDDefs{$response->program_name($r)} = { %HoSDAttr };
    }
}   # end for each response

return;
}   # end of format_sd_defs


#--------------------------------------------------------------------#
# display_attributes - displays the attributes names and values for  #
#   each element stored in %$rHoAttr. Only the attributes that       #
#   are listed in the array $r_attributes are displayed using the    #
#   appropriate output format (long, delimitter, or tabular).        #
#   If $r_attributes is empty all attributes in %$rHoAttr are        #
#   displayed.                                                       #
#                                                                    #
# Parameters:                                                        #
#   $col_title        input   Title/Header that gets displayed       #
#                             before any attributes.                 #
#   $row_title        input   Title/Header that gets displayed       #
#                             before each new attribute.             #
#   @$r_attributes    input   Attribute names from command line.     #
#   @$rLoAttr         input   Reference to List of Attributes Names  #
#   %$rHoAttr         input   Reference to Hash of Attributes        #
#                                                                    #
# Returns:                                                           #
#   $rc                       Return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_Long_Format  input   TRUE if should display one per line.   #
#   $Opt_Table_Format input   TRUE if should display in table form.  #
#   $Opt_Delm_Format  input   TRUE if should display with delimiter. #
#   $Opt_Delm_Str     input   Actual delimiter to display with.      #
#   $Opt_No_HDR       input   TRUE if should not display header.     #
#--------------------------------------------------------------------#
sub display_attributes
{
my($col_title, $row_title, $r_attributes, $rLoAttr, $rHoAttr) = @_;

my $print_format = "long";
my $delim = "";

# Determine if displaying in long, delimiter or tabular/column format.
if ($Opt_Long_Format) {
    $print_format = "long";
}
elsif ($Opt_Table_Format) {
    $print_format = "column";
}
elsif ($Opt_Delm_Format) {
    $print_format = "delim";
    $delim = $Opt_Delm_Str;
}

# Display the attributes in the order that they were requested
# on the command line.  If no attribute names were specified on
# the command line display them in the order that RMC returned
# them.

if (scalar(@$r_attributes) == 0) {
    $r_attributes = $rLoAttr;
}

# For debugging to reference one element
# $rHoAttr->{$attr_name}[$row]{at_value}

my $rc = display_resource_data($print_format, $Opt_No_HDR,
    $r_attributes, $row_title, $rHoAttr, $delim, $col_title);

return $rc;
}   # end display_attributes


#--------------------------------------------------------------------#
# display_sd_defs - displays the SD definition for the resource      #
#   or resource class persistent or dynamic SD attributes.           #
#   Zero or more SDs may have been formatted to be displayed.        #
#                                                                    #
# Parameters:                                                        #
#   $resource         input   Name of resource.                      #
#   @$rLoSDAttr       input   Reference to List of Attributes        #
#   %$rHoSDDefs       input   Reference to Hash of Attributes        #
#                                                                    #
# Returns:                                                           #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   $Opt_LS_Class     input   TRUE if listing resource class SD defs #
#   $Opt_LS_PAttr     input   TRUE if listing Persistent Attributes. #
#   $Opt_LS_DAttr     input   TRUE if listing Dynamic Attributes.    #
#   $Opt_No_HDR       input   TRUE if should not display header.     #
#--------------------------------------------------------------------#
sub display_sd_defs
{
my($resource, $rLoSDAttr, $rHoSDDefs) = @_;

my ($col_title, $row_title);

if (!$Opt_No_HDR) {
    if ($Opt_LS_Class) {
        if ($Opt_LS_PAttr) {
            printIMsg("IMsglsrsrcdefLsRsrcClassPSDDefHdr", $resource);
        }
        else {
            printIMsg("IMsglsrsrcdefLsRsrcClassDSDDefHdr", $resource);
        }
    }
    else {
        if ($Opt_LS_PAttr) {
            printIMsg("IMsglsrsrcdefLsRsrcPSDDefHdr", $resource);
        }
        else {
            printIMsg("IMsglsrsrcdefLsRsrcDSDDefHdr", $resource);
        }
    }
}
   
$row_title = "sd_element";          # use programmic name for NLS
my @fields = ();                    # display all fields in HoSDDefs
my @sd_keys = keys %$rHoSDDefs;
my $sd_def_cnt = scalar(@sd_keys);
my $badrc = 0;
for (my $s = 0; $s < $sd_def_cnt; $s++) {
    $col_title = "program_name $sd_keys[$s]:";
    $rc = display_attributes($col_title, $row_title, \@fields,
        $rLoSDAttr, $$rHoSDDefs{$sd_keys[$s]});
    if ($rc != 0 && $badrc == 0) {
        $badrc = $rc; 
    } 
}

return $badrc;
}   # end display_sd_defs


#--------------------------------------------------------------------#
# error_check - checks the return code from the RMC function and     #
#   the error response return code.  If an error is detected         #
#   appropriate error messages will be displayed.                    #
#                                                                    #
# Parameters:                                                        #
#   $rmc_function     in      Name of the rmc function that was      #
#                             called and whose error code we are     #
#                             checking.                              #
#   $rmc_class        in      The rmc class name.                    #
#   $response         in      RMC response.                          #
#   $rmc_rc           in      The rmc function return code.          #
#   $error            in      The error response.                    #
#                                                                    #
# Return:                                                            #
#   $rc                       return code.                           #
#                                                                    #
# Global References:                                                 #
#   None.                                                            #
#--------------------------------------------------------------------#
sub error_check
{
my ($rmc_function, $rmc_class, $response, $rmc_rc, $error) = @_;

my $rc = 0;
my $err_rc = $error->errnum();

if ($rmc_rc != 0) {
    printEMsg("EMsglsrsrcdefLsRsrcDefError", $rmc_class);
    my $rmc_rc_hex = sprintf "0x%8.8lx", $rmc_rc;
    printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function,
        $rmc_rc, $rmc_rc_hex);
    $rc = MC_CLI_RMC_ERROR;
    return $rc;
}

# Check the errnum in each of the RMC responses
for (my $r = 0; $r < $response->array_count; $r++) {
    # get the error that goes with the specific response
    if ($r > 0) {
        $response->error($error, $r);
        $err_rc = $error->errnum();
    }
    if ($err_rc != 0) {
        if ($err_rc == RMC_ECLASSNOTDEFINED) {
            printCEMsg("EMsgMCcliClassNotDef", $rmc_class);
            $rc = MC_CLI_USER_ERROR;
        }
        elsif ($err_rc == RMC_ESDNOTDEFINED) {
            # Not having any SD Defs is not an error just don't
            # display anything
            $Verbose && print STDERR $error->error_msg;
            $rc = 0;
        }
        elsif ($err_rc == RMC_EBADATTRNAM) {
            print STDERR $error->error_msg;
            $rc = MC_CLI_USER_ERROR;
        }   
        elsif ($err_rc == RMC_EACCESS) {
            print STDERR $error->error_msg;
            $rc = MC_CLI_USER_ERROR;
        }
        else {
            printEMsg("EMsglsrsrcdefLsRsrcDefError", $rmc_class);
            my $err_rc_hex = sprintf "0x%8.8lx", $err_rc;
            printCEMsg("EMsgMCcliMCFunctionFailure", $rmc_function, 
                $err_rc, $err_rc_hex);
            print STDERR $error->error_msg; 
            $rc = MC_CLI_RMC_ERROR;
        }
    }   # end if
}   # end for

return $rc;
}   # end error_check
